package personal.wang.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yaml.snakeyaml.Yaml;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class YamlReader {
    private static Logger logger = LoggerFactory.getLogger(YamlReader.class);

    private static final Map<String , Map<String , Map<String , Object>>> CACHE_MAP_VALUES = new ConcurrentHashMap<>();
    public static final String SEPARATOR = "." ;

    public static Object getResourceValue(String configPath, String key) {
        return getValueByeKeyOriginal(key , getResourceConfig(configPath));
    }
    public static String getValueAsString(String configPath, String key){
        Object valueByeKeyOriginal = getValueByeKeyOriginal(key, getResourceConfig(configPath));
        return String.valueOf(valueByeKeyOriginal);
    }

    public static String getValueAsString(String key){
        Object valueByeKeyOriginal = getValueByeKeyOriginal(key, getDefaultFile());
        return String.valueOf(valueByeKeyOriginal);
    }
    public static Map<String ,Object> getValueAsMap(String configPath, String key){
        Object valueByeKeyOriginal = getValueByeKeyOriginal(key, getResourceConfig(configPath));
        return (Map<String , Object>)valueByeKeyOriginal;
    }
    private static Object getValueByeKeyOriginal(String key, Map<String , Map<String , Object>> mapConfig) {

        if(Objects.isNull(mapConfig)){
            logger.error("map 对象为 null ，无法解析");
            return null;
        }
        String[] separatorKeys = null ;
        if(key.contains(SEPARATOR)){
            separatorKeys = key.split("\\.");
        }else{
            return mapConfig.get(key);
        }
        Map<String , Map<String , Object>> finalValue = null ;
        for(int i = 0 ; i < separatorKeys.length -1 ; i++ ){
            if(i == 0){
                finalValue = (Map)mapConfig.get(separatorKeys[i]);
                continue;
            }
            if(Objects.isNull(finalValue)){
                break ;
            }
            finalValue = (Map)finalValue.get(separatorKeys[i]);
        }
        return Objects.isNull(finalValue ) ? null : finalValue.get(separatorKeys[separatorKeys.length -1]);
    }
    /**
     * @desc: 此方法是从 jar 包中读取配置文件的信息到 cach_map_value 中
     * */
    private static Map<String , Map<String , Object>> getResourceConfig(String configPath) {
        Map<String , Map<String,Object>> inputStreamProperties = null ;
        try{
            if(!CACHE_MAP_VALUES.containsKey(configPath)){
                InputStream in = new FileInputStream(configPath);
                inputStreamProperties = getStreamConfig(in);
                CACHE_MAP_VALUES.put(configPath , inputStreamProperties);
            }else{
                inputStreamProperties = CACHE_MAP_VALUES.get(configPath);
            }
        }catch (Exception e){
            logger.error(" 初始化 yaml 文件失败 , {}" , e);
        }
        return  inputStreamProperties ;
    }

    private static Map<String , Map<String , Object>> getDefaultFile(){
        Map<String , Map<String , Object>> rs = null;
        if(CACHE_MAP_VALUES.size() >= 1){
            Collection<Map<String, Map<String, Object>>> values = CACHE_MAP_VALUES.values();
            for (Map<String, Map<String, Object>> value : values) {
                rs = value;
            }
        }
       return rs;
    }

    private static Map<String, Map<String, Object>> getStreamConfig(InputStream in) {
        Yaml yaml = new Yaml();
        Map<String , Map<String , Object>> properites = null ;
        try{
            properites = yaml.loadAs(in, HashMap.class);
        }catch (Exception e){
            logger.error("加载 yaml 文件失败,{}",e);
        }finally {
            if(!Objects.isNull(in)){
                try{
                    in.close();
                }catch (Exception e){
                    logger.error(" 关闭输入流失败，{}",e);
                }
            }
        }
        return properites;
    }

    public static Object getFileValue(String configName, String configContent, String key) {
        if(!CACHE_MAP_VALUES.containsKey(configName)){
            CACHE_MAP_VALUES.put(configName , getStreamConfig(new ByteArrayInputStream(configContent.getBytes(StandardCharsets.UTF_8))));
        }
        return getValueByeKeyOriginal(key , CACHE_MAP_VALUES.get(configName));
    }
}
